package com.bytebuddytest.quickstart;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.function.Function;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2023/08/14 10:35:33
 */
@DisplayName("byte-buddy 快速入门")
public class ByteBuddyQuickStartTest {

    @Test
    public void testHelloWorld() throws InstantiationException, IllegalAccessException {
        Class<?> dynamicType = new ByteBuddy()
                .subclass(Object.class)
                .method(ElementMatchers.named("toString"))
                .intercept(FixedValue.value("Hello World!"))
                .make()
                .load(getClass().getClassLoader())
                .getLoaded();

        System.out.println(dynamicType.newInstance());
        assertEquals("Hello World!", dynamicType.newInstance().toString());
    }

    @Test
    public void testInterceptor() throws InstantiationException, IllegalAccessException {
        Class<? extends Function> dynamicType = new ByteBuddy()
                .subclass(Function.class)
                .method(ElementMatchers.named("apply"))
                .intercept(MethodDelegation.to(new GreetingInterceptor()))
                .make()
                .load(getClass().getClassLoader())
                .getLoaded();

        Object functionReturn = dynamicType.newInstance().apply("Byte Buddy");
        System.out.println(functionReturn);
        assertEquals("Hello from Byte Buddy", functionReturn);
    }

    @Test
    public void testGeneralInterceptor() throws InstantiationException, IllegalAccessException {
        Class<? extends Function> dynamicType = new ByteBuddy()
                .subclass(Function.class)
                .method(ElementMatchers.named("apply"))
                .intercept(MethodDelegation.to(new GeneralInterceptor()))
                .make()
                .load(getClass().getClassLoader())
                .getLoaded();

        assertNull(dynamicType.newInstance().apply("Byte Buddy"));
    }

    @Test
    public void testTimerAgent() {
        // -javaagent:/Users/yth/IdeaProjects/bytebuddy-demo/target/bytebuddy-demo-1.0-SNAPSHOT.jar
        // watch console output
        new HelloWorldTimed().print();
        /*
            Hello World!
            public void com.bytebuddytest.quickstart.HelloWorldTimed.print() took 35
         */
    }

}
